import { HttpStatus, Injectable, Logger } from '@nestjs/common';
import {
  ArgumentsHost,
  Catch,
  ExceptionFilter,
  HttpException,
} from '@nestjs/common';
import { Request, Response } from 'express';
import { v4 as uuid } from 'uuid';

@Catch()
@Injectable()
export class GlobalExceptionFilter implements ExceptionFilter {
  private readonly logger = new Logger();
  constructor() {}
  async catch(exception: HttpException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const request = ctx.getRequest<Request>();
    const response = ctx.getResponse<Response>();
    const status =
      exception instanceof HttpException
        ? exception.getStatus()
        : HttpStatus.INTERNAL_SERVER_ERROR;
    const message: unknown =
      exception['response'] ||
      exception.message ||
      exception.name ||
      'Internal Server Error';
    let params = {};
    if (Object.keys(request.query).length > 0) {
      params = { ...params, ...request.query };
    }
    if (Object.keys(request.params).length > 0) {
      params = { ...params, ...request.params };
    }
    if (Object.keys(request.body).length > 0) {
      params = { ...params, ...request.body };
    }

    const { method, path } = request;
    const traceId = uuid();
    request['traceId'] = traceId;
    const responseData = {
      msg: message,
      code: -1,
      traceId,
      timestamp: new Date().toISOString(),
      path: request.url,
      method: request.method,
    };
    this.logger.error(
      `${traceId} ${method} ${path} request: ${JSON.stringify(params)} response: ${JSON.stringify(responseData)} ${exception?.stack}`,
    );
    this.logger.log(
      `${traceId} ${method} ${path} request: ${JSON.stringify(params)} response: ${JSON.stringify(responseData)}`,
    );
    response.status(status).json(responseData);
  }
}
